package com.candy.service.impl;

import com.candy.dao.AccountDao;
import com.candy.dao.impl.AccountDaoImpl;
import com.candy.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.Date;

/**
 * 使用xml方法进行配置时：
 * <bean id="AccountService" class="com.candy.service.impl.AccountServiceImpl" scope="prototype"
 * init-method="initMethod" destroy-method="destroyMethod">
 * <property name="name" value="白展堂"></property>
 * </bean>
 *
 * 注解大致课分为四类：
 * 进行对象创建的：
 *          与xml配置时的bean标签的作用一致
 *          Component:
 *          作用：用于把当前类对象存入spring容器中
 *          Controller：一般用在表现层
 *          Service：一般用在业务层
 *          Repository：一般用在持久层
 *          以上三个注解他们的作用和属性与Component是一模一样
 *          他们三个是spring框架为我们提供明确的三层使用的注解，使我们的三层对象更加清晰
 * 用于属性注入的：与xml配置时的property标签的作用是一样的
 *      Autowired:
 *     作用：自动按照类型注入。只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配，就可以注入成功
 *           如果ioc容器中没有任何bean的类型和要注入的变量类型匹配，则报错。
 *           如果Ioc容器中有多个类型匹配时：
 *     出现位置：
 *         可以是变量上，也可以是方法上
 *     细节：
 *         在使用注解注入时，set方法就不是必须的了。
 *     Qualifier:
 *     作用：在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。但是在给方法参数注入时可以
 *     属性：
 *         value：用于指定注入bean的id。
 *     Resource
 *     作用：直接按照bean的id注入。它可以独立使用
 *     属性：
 *         name：用于指定bean的id。
 *     以上三个注入都只能注入其他bean类型的数据，而基本类型和String类型无法使用上述注解实现。
 *     Value
 *     作用：用于注入基本类型和String类型的数据
 *     属性：
 *         value：用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式）
 *                 SpEL的写法：${表达式}
 *
 * 指定作用范围：与xml配置时用到的scope属性的作用是一致的
 *  `    Scope
 *          作用：用于指定bean的作用范围
 *          属性：
 *              value：指定范围的取值。常用取值：singleton prototype
 * 与声明周期相关的：与xml配置中得到init-method 、destroy-method作用是一致的
 *
 *      PreDestroy
 *          作用：用于指定销毁方法
 *      PostConstruct
 *          作用：用于指定初始化方法
 */
@Component(value = "AccountService")
@Scope(value = "singleton")
public class AccountServiceImpl implements AccountService {
//    @Autowired
//    @Qualifier(value = "accountDaoImpl")
//    @Resource(name = "accountDaoImpl")
    @Value("#{accountDaoImpl}")
    private AccountDao accountDao;
    @Value("张三")
    private String name;
    private Integer age;
    private Date birthday;

    public AccountServiceImpl() {
        System.out.println("创建对象");
    }

    public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    @Override
    public void saveAccount() {
        accountDao.saveAccont();
        System.out.println(name);


    }

    @PostConstruct
    public void initMethod(){
        System.out.println("我是初始化方法");
    }
    @PreDestroy
    public  void  destroyMethod(){
        System.out.println("我是对象销毁前调用的方法");
    }


}
